
/**
 * 自定义数组类
 */
public class Array<T> {
    private T[] data;
    private int size;

    //有参构造方法,自定义容量大小
    public Array(int capacity){
        //泛型创建对象，不支持直接new
        this.data = (T[]) new Object[capacity];
        this.size = 0;
    }

    //无参，设置一个默认容量
    public Array(){
        //this()调用了有参构造方法
        this(10);
    }

    //获取数组中的元素个数
    public int getSize(){
        return size;
    }

    //获取数组容量
    public  int getCapacity(){
        return data.length;
    }

    //判断数组是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    /**
     * 添加元素操作
     *      1.向指定位置添加元素
     *      2.维护size
     */
    //在所有元素后添加一个新元素
    public void addLast(T e){
//        if(size == data.length){
//            throw new IllegalArgumentException("addLast Failed,Array is full");
//        }
//        data[size] = e;
//        size++;
        add(size,e);
    }

    //在所有元素前添加一个新元素
    public void addFirst(T e){
        add(0,e);
    }

    //向数组的指定位置添加元素
    public void add(int index,T e){
        //判断参数是否合法
        if(index <0 || index > size){
            throw new IllegalArgumentException("add Failed,Require index >=0 and index <= size");
        }
        //容量不够，进行扩容
        if(size == data.length){
            resize(2 * data.length);
        }
        //将元素从后开始，一个一个往后移动,直到index索引位置。
        for(int i = size-1;i>=index;i--){
            data[i+1] = data[i];
        }
        data[index] = e;
        size++;
    }

    //获取指定索引位置的元素
    T get(int index){
        if(index <0 || index>=size){
            throw new IllegalArgumentException("get Failed,Require index >=0 and index < size");
        }
        return data[index];
    }

    //获取第一个元素
    public T getFirst(){
        return get(0);
    }

    //获取最后一个元素
    public T getLast(){
        return get(size - 1);
    }

    //修改指定索引位置的元素
    void set(int index,T e){
        if(index <0 || index>=size){
            throw new IllegalArgumentException("get Failed,Require index >=0 and index < size");
        }
        data[index]=e;
    }

    //查找数组中出现的第一个元素e的索引
    public int find(T e){
        for(int i=0;i<size;i++){
            if(data[i].equals(e)){
                return i;
            }
        }
        return -1;
    }
    //查找数组中所有元素e的索引
    public String findAll(T e){
        StringBuilder res = new StringBuilder();
        for(int i=0;i<size;i++){
            if(data[i].equals(e)){
                res.append(i);
                if(i != size-1)
                    res.append(",");
            }
        }
        return res.toString();
    }


    //查找数组中是否包含有e
    public boolean contains(T e){
        for(int i=0;i<size;i++){
            if(data[i].equals(e)){
                return true;
            }
        }
        return false;
    }

    //删除指定位置的元素,返回被删除的元素值
    public T remove(int index){
        if(index <0 || index>=size){
            throw new IllegalArgumentException("get Failed,Require index >=0 and index < size");
        }
        T res = data[index];
        for(int i=index+1;i<size;i++){
            data[i-1] = data[i];
        }
        size --;
        data[size] = null;
        //缩容
        if(size == data.length/2){
            resize(data.length/2);
        }
        return res;
    }

    //删除数组中的第一个元素，返回元素值
    public T removeFirst(){
        return remove(0);
    }

    //删除数组最后一个元素，返回元素值
    public T removeLast(){
        return remove(size-1);
    }

    //删除数组中出现的第一个元素e
    public boolean removeElement(T e){
        int i = find(e);
        if(i != -1){
            remove(i);
            return true;
        }
        return false;
    }

    //删除数组中所有的元素e
    public boolean remove2Element(T e){
        String[] indexAll = findAll(e).split(",");
        for(String index:indexAll){
            int i = Integer.parseInt(index);
            remove(i);
        }
        if(find(e) == -1){
            return true;
        }
        return false;
    }

    //交换元素位置
    public void swap(int i,int j){
        if(i<0 || i>=size || j<0 || j >=size){
            throw new IllegalArgumentException("index is Illegal");
        }

        T t = data[i];
        data[i] = data[j];
        data[j] = t;

    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("Array: size = %d, capacity = %d\n",size,data.length));
        res.append("[");
        for(int i=0;i<size;i++){
            res.append(data[i]);
            if(i != size-1){
                res.append(", ");
            }
        }
        res.append("]");
        return res.toString();
    }

    //扩容或缩容
    private void resize(int newCapacity){
        T[] newData = (T[]) new Object[newCapacity];
        for(int i=0;i<size;i++){
            newData[i] = data[i];
        }
        data = newData;
    }
}
